package com.atguigu.gmall.product.service.impl;
import java.util.Date;
import com.alibaba.fastjson.JSON;
import com.atguigu.gmall.feign.search.GoodsFeignClient;
import com.atguigu.gmall.product.entity.*;
import com.atguigu.gmall.product.mapper.BaseTrademarkMapper;
import com.atguigu.gmall.product.mapper.SkuAttrValueMapper;
import com.atguigu.gmall.product.service.*;
import com.atguigu.gmall.product.vo.AttrValueConcatVo;
import com.atguigu.gmall.search.entity.Goods;
import com.atguigu.gmall.search.entity.SearchAttr;
import com.google.common.collect.Lists;
import com.atguigu.gmall.item.vo.CategoryView;
import java.math.BigDecimal;
import java.util.List;
import java.util.Map;
import java.util.concurrent.*;
import java.util.stream.Collectors;

import com.atguigu.gmall.item.vo.SkuInfoDetailVo;
import com.atguigu.gmall.product.dto.SkuInfoDto;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.atguigu.gmall.product.mapper.SkuInfoMapper;
import lombok.extern.slf4j.Slf4j;
import org.redisson.api.RBloomFilter;
import org.redisson.api.RedissonClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.PostConstruct;

/**
* @author Administrator
* @description 针对表【sku_info(库存单元表)】的数据库操作Service实现
* @createDate 2023-11-01 15:32:54
*/
@Service
@Slf4j
public class SkuInfoServiceImpl extends ServiceImpl<SkuInfoMapper, SkuInfo> implements SkuInfoService {

    @Autowired
    private SkuImageService skuImageService ;

    @Autowired
    private SkuAttrValueService skuAttrValueService ;

    @Autowired
    private SkuSaleAttrValueService skuSaleAttrValueService ;

    @Autowired
    private SkuInfoMapper skuInfoMapper ;

    @Autowired
    private RedisTemplate<String , String> redisTemplate ;

    @Autowired
    private BaseCategory1Service baseCategory1Service ;

    @Autowired
    private SpuSaleAttrService spuSaleAttrService ;

    @Autowired
    private BaseTrademarkMapper baseTrademarkMapper ;

    @Autowired
    private SkuAttrValueMapper skuAttrValueMapper ;

    @Override
    public Page<SkuInfo> findByPage(Integer pageNo, Integer pageSize) {
        Page<SkuInfo> page = new Page<>(pageNo , pageSize) ;
        this.page(page) ;
        return page;
    }

    @Override
    @Transactional
    public void saveSkuInfo(SkuInfoDto skuInfoDto) {

        // 保存sku的基本数据
        SkuInfo skuInfo = new SkuInfo() ;
        skuInfo.setSpuId(skuInfoDto.getSpuId());
        skuInfo.setPrice(skuInfoDto.getPrice());
        skuInfo.setSkuName(skuInfoDto.getSkuName());
        skuInfo.setSkuDesc(skuInfoDto.getSkuDesc());
        skuInfo.setWeight(skuInfoDto.getWeight());
        skuInfo.setTmId(skuInfoDto.getTmId());
        skuInfo.setCategory3Id(skuInfoDto.getCategory3Id());
        skuInfo.setSkuDefaultImg(skuInfoDto.getSkuDefaultImg());
        skuInfo.setIsSale(0);       // 新添加sku不能直接进行销售
        this.save(skuInfo) ;

        // 保存sku的图片数据
        List<SkuImage> skuImageList = skuInfoDto.getSkuImageList();
        skuImageList = skuImageList.stream().map(skuImage -> {
            skuImage.setSkuId(skuInfo.getId());
            return skuImage ;
        }).collect(Collectors.toList()) ;
        skuImageService.saveBatch(skuImageList) ;

        // 保存sku的平台属性值数据
        List<SkuAttrValue> skuAttrValueList = skuInfoDto.getSkuAttrValueList();
        skuAttrValueList = skuAttrValueList.stream().map(skuAttrValue -> {
            skuAttrValue.setSkuId(skuInfo.getId());
            return skuAttrValue ;
        }).collect(Collectors.toList()) ;
        skuAttrValueService.saveBatch(skuAttrValueList) ;

        // 保存sku的销售属性值数据
        List<SkuSaleAttrValue> skuSaleAttrValueList = skuInfoDto.getSkuSaleAttrValueList();
        skuSaleAttrValueList = skuSaleAttrValueList.stream().map(skuSaleAttrValue -> {
            skuSaleAttrValue.setSkuId(skuInfo.getId());
            skuSaleAttrValue.setSpuId(skuInfoDto.getSpuId());
            return skuSaleAttrValue ;
        }).collect(Collectors.toList()) ;
        skuSaleAttrValueService.saveBatch(skuSaleAttrValueList) ;

        // 把新的skuId的添加到布隆过滤器中
        RBloomFilter<Object> bloomFilter = redissonClient.getBloomFilter("skuIds-bloom-filter");
        bloomFilter.add(skuInfo.getId()) ;

    }

    @Autowired
    private GoodsFeignClient goodsFeignClient ;

    @Override
    public void onSale(Long skuId) {

        // 删除Redis中的数据
//        redisTemplate.delete("sku:info:" + skuId) ;

        // 修改数据库
        SkuInfo skuInfo = new SkuInfo() ;
        skuInfo.setId(skuId);
        skuInfo.setIsSale(1);
        this.updateById(skuInfo) ;

        // 延迟删除
//        ScheduledExecutorService scheduledThreadPool = Executors.newScheduledThreadPool(10);
//        scheduledThreadPool.schedule(() -> {
//            redisTemplate.delete("sku:info:" + skuId) ;
//            log.info("延迟删除的任务执行了....");
//        } , 300 , TimeUnit.MILLISECONDS) ;


        // 请求search微服务的接口，保存SKU的数据到ES索引库中
        Goods goods = buildGoods(skuId);
        goodsFeignClient.saveGoods(goods) ;

    }

    // 构建的Goods对象
    private Goods buildGoods(Long skuId) {

        Goods goods = new Goods() ;

        // 根据skuId查询sku的基本数据
        CompletableFuture<SkuInfo> cf1 = CompletableFuture.supplyAsync(() -> {
            SkuInfo skuInfo = this.getById(skuId);
            goods.setId(skuInfo.getId());
            goods.setDefaultImg(skuInfo.getSkuDefaultImg());
            goods.setTitle(skuInfo.getSkuName());
            goods.setPrice(skuInfo.getPrice());
            goods.setCreateTime(new Date());
            goods.setHotScore(0L);          // 热度分
            return skuInfo;
        } , threadPoolExecutor);

        // 根据品牌的id查询品牌数据
        CompletableFuture<Void> cf2 = cf1.thenAcceptAsync((skuInfo) -> {
            Long tmId = skuInfo.getTmId();
            BaseTrademark baseTrademark = baseTrademarkMapper.selectById(tmId);
            goods.setTmId(baseTrademark.getId());
            goods.setTmName(baseTrademark.getTmName());
            goods.setTmLogoUrl(baseTrademark.getLogoUrl());
        }, threadPoolExecutor);


        // 根据skuId查询三级分类数据
        CompletableFuture<Void> cf3 = CompletableFuture.runAsync(() -> {
            CategoryView categoryView = baseCategory1Service.findCategoryViewBySkuId(skuId);
            goods.setCategory1Id(categoryView.getCategory1Id());
            goods.setCategory1Name(categoryView.getCategory1Name());
            goods.setCategory2Id(categoryView.getCategory2Id());
            goods.setCategory2Name(categoryView.getCategory2Name());
            goods.setCategory3Id(categoryView.getCategory3Id());
            goods.setCategory3Name(categoryView.getCategory3Name());
        }, threadPoolExecutor);

        // 根据skuId查询sku的平台属性和平台属性值
        CompletableFuture<Void> cf4 = CompletableFuture.runAsync(() -> {
            List<SearchAttr> searchAttrList = skuAttrValueMapper.findSkuAttrNameAndValueNameBySkuId(skuId) ;
            goods.setAttrs(searchAttrList);
        }, threadPoolExecutor);

        // 多任务的组合
        CompletableFuture.allOf(cf1 , cf2 , cf3 , cf4).join() ;

        // 返回
        return goods ;

    }

    @Override
    public void cancelSale(Long skuId) {
        SkuInfo skuInfo = new SkuInfo() ;
        skuInfo.setId(skuId);
        skuInfo.setIsSale(0);
        this.updateById(skuInfo) ;

        // 远程调用service-search微服务的接口，根据skuId的删除数据
        goodsFeignClient.deleteById(skuId) ;
    }

    @Override
    public SkuInfo findSkuInfoAndImageBySkuId(Long skuId) {
        return skuInfoMapper.findSkuInfoAndImageBySkuId(skuId) ;
    }

    @Override
    public List<Long> findAllSkuIds() {
        List<SkuInfo> skuInfoList = this.list();
        List<Long> skuIds = skuInfoList.stream().map(skuInfo -> skuInfo.getId()).collect(Collectors.toList());
        return skuIds;
    }

    @Autowired
    private ThreadPoolExecutor threadPoolExecutor ;

    @Override
    public SkuInfoDetailVo findSkuInfoDetail(Long skuId) {

        SkuInfoDetailVo skuInfoDetailVo = new SkuInfoDetailVo() ;

        // 根据skuId查询sku的基本数据以及图片数据
        SkuInfo skuInfo = this.findSkuInfoAndImageBySkuId(skuId);
        if(skuInfo == null) {
            return skuInfoDetailVo ;
        }
        skuInfoDetailVo.setSkuInfo(skuInfo);
        skuInfoDetailVo.setPrice(skuInfo.getPrice());

        // 根据skuId的查询三级分类数据
        CompletableFuture<Void> cf1 = CompletableFuture.runAsync(() -> {
            CategoryView categoryView = baseCategory1Service.findCategoryViewBySkuId(skuId);
            skuInfoDetailVo.setCategoryView(categoryView);
        }, threadPoolExecutor);

        // 根据skuId查询spu的销售属性和销售属性值
        CompletableFuture<Void> cf2 = CompletableFuture.runAsync(() -> {

            List<SpuSaleAttr> spuSaleAttrAndSaleAttrValue = spuSaleAttrService.findSpuSaleAttrAndSaleAttrValue(skuId);
            skuInfoDetailVo.setSpuSaleAttrList(spuSaleAttrAndSaleAttrValue);
        }, threadPoolExecutor);

        // 根据skuId查询所有的sku的销售属性值的组合
        CompletableFuture<Void> cf3 = CompletableFuture.runAsync(() -> {
            List<AttrValueConcatVo> concatVoList = skuSaleAttrValueService.findAttrValueConcatBySkuId(skuId);
            Map<String, Long> map = concatVoList.stream().collect(Collectors.toMap(attrValueConcatVo -> attrValueConcatVo.getAttrValueConcat(), attrValueConcatVo -> attrValueConcatVo.getSkuId()));
            skuInfoDetailVo.setValuesSkuJson(JSON.toJSONString(map));
        }, threadPoolExecutor);

        // 阻塞线程
        CompletableFuture.allOf(cf1 , cf2 , cf3).join() ;

        // 返回
        return skuInfoDetailVo;
    }

    public SkuInfoDetailVo findSkuInfoDetailThreadPoolExecutor(Long skuId) {

        SkuInfoDetailVo skuInfoDetailVo = new SkuInfoDetailVo() ;

        // 根据skuId查询sku的基本数据以及图片数据
        SkuInfo skuInfo = this.findSkuInfoAndImageBySkuId(skuId);
        if(skuInfo == null) {
            return skuInfoDetailVo ;
        }
        skuInfoDetailVo.setSkuInfo(skuInfo);
        skuInfoDetailVo.setPrice(skuInfo.getPrice());

        // 创建CountDownLatch
        CountDownLatch countDownLatch = new CountDownLatch(3) ;

        threadPoolExecutor.submit(() -> {
            // 根据skuId的查询三级分类数据
            CategoryView categoryView = baseCategory1Service.findCategoryViewBySkuId(skuId);
            skuInfoDetailVo.setCategoryView(categoryView);
            countDownLatch.countDown();
        }) ;

        threadPoolExecutor.submit(() -> {
            // 根据skuId查询spu的销售属性和销售属性值
            List<SpuSaleAttr> spuSaleAttrAndSaleAttrValue = spuSaleAttrService.findSpuSaleAttrAndSaleAttrValue(skuId);
            skuInfoDetailVo.setSpuSaleAttrList(spuSaleAttrAndSaleAttrValue);
            countDownLatch.countDown();
        }) ;

        threadPoolExecutor.submit(() -> {
            // 根据skuId查询所有的sku的销售属性值的组合
            List<AttrValueConcatVo> concatVoList =  skuSaleAttrValueService.findAttrValueConcatBySkuId(skuId) ;
            Map<String, Long> map = concatVoList.stream().collect(Collectors.toMap(attrValueConcatVo -> attrValueConcatVo.getAttrValueConcat(), attrValueConcatVo -> attrValueConcatVo.getSkuId()));
            skuInfoDetailVo.setValuesSkuJson(JSON.toJSONString(map));
            countDownLatch.countDown();
        }) ;

        try {
            countDownLatch.await();     // 阻塞主线程
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }

        return skuInfoDetailVo;
    }

    @Autowired
    private RedissonClient redissonClient ;

    @PostConstruct
    public void initBloomFilter() {
        RBloomFilter<Object> bloomFilter = redissonClient.getBloomFilter("skuIds-bloom-filter");
        bloomFilter.tryInit(100000 , 0.0001) ;
        List<Long> skuIds = findAllSkuIds();
        skuIds.forEach(skuId -> {
            bloomFilter.add(skuId) ;
        });
        log.info("布隆过滤器初始化完毕....");
    }

}




